import { Request, Response } from 'express';
import { Device } from '../models/device';
import { DeviceData } from '../models/deviceData.model';
import mqttService from '../services/mqttService';
import { broadcast } from '../app';
import { Op } from 'sequelize';
import multer from 'multer';
import path from 'path';
import fs from 'fs';

// 配置multer存储
const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    const uploadDir = path.join(__dirname, '../../uploads');
    if (!fs.existsSync(uploadDir)) {
      fs.mkdirSync(uploadDir, { recursive: true });
    }
    cb(null, uploadDir);
  },
  filename: (req, file, cb) => {
    const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
    cb(null, file.fieldname + '-' + uniqueSuffix + path.extname(file.originalname));
  }
});

export const upload = multer({ 
  storage,
  fileFilter: (req, file, cb) => {
    const allowedTypes = ['.bin', '.hex'];
    const ext = path.extname(file.originalname).toLowerCase();
    if (allowedTypes.includes(ext)) {
      cb(null, true);
    } else {
      cb(new Error('只允许上传.bin或.hex格式的固件文件'));
    }
  },
  limits: {
    fileSize: 10 * 1024 * 1024 // 限制文件大小为10MB
  }
});

export const registerDevice = async (req: Request, res: Response): Promise<void> => {
  try {
    const { deviceId, name, type, password } = req.body;
    
    // 确保用户已认证
    if (!req.user || !req.user._id) {
      res.status(401).json({ message: '未授权访问' });
      return;
    }

    const userId = req.user._id;

    // 验证必填字段
    if (!deviceId || !name || !type || !password) {
      res.status(400).json({ message: '缺少必要字段' });
      return;
    }

    const existingDevice = await Device.findOne({ deviceId });
    if (existingDevice) {
      res.status(400).json({ message: '设备ID已存在' });
      return;
    }

    const device = await Device.create({
      deviceId,
      name,
      type,
      password,
      status: 'offline',
      lastHeartbeat: new Date(),
      userId
    });

    res.status(201).json(device);
  } catch (error: any) {
    console.error('注册设备失败:', error);
    res.status(500).json({ 
      message: '注册设备失败', 
      error: error.message || '未知错误'
    });
  }
};

export const deleteDevice = async (req: Request, res: Response): Promise<void> => {
  try {
    const { deviceId } = req.params;
    const userId = req.user._id;

    const device = await Device.findOne({ deviceId, userId });
    if (!device) {
      res.status(404).json({ message: '设备不存在或无权删除' });
      return;
    }

    await Device.findOneAndDelete({ deviceId, userId });
    await DeviceData.deleteMany({ deviceId });
    res.json({ message: '设备删除成功' });
  } catch (error) {
    res.status(500).json({ message: '删除设备失败', error });
  }
};

export const updateDevicePassword = async (req: Request, res: Response): Promise<void> => {
  try {
    const { deviceId } = req.params;
    const { password } = req.body;
    const userId = req.user._id;

    const device = await Device.findOneAndUpdate(
      { deviceId, userId },
      { password },
      { new: true }
    );

    if (!device) {
      res.status(404).json({ message: '设备不存在或无权更新密码' });
      return;
    }

    res.json(device);
  } catch (error) {
    res.status(500).json({ message: '更新设备密码失败', error });
  }
};

export const getDevices = async (req: Request, res: Response): Promise<void> => {
  try {
    const userId = req.user._id;
    const devices = await Device.find({ userId });
    res.json(devices);
  } catch (error) {
    res.status(500).json({ message: '获取设备列表失败', error });
  }
};

export const getDeviceData = async (req: Request, res: Response): Promise<void> => {
  try {
    const { deviceId } = req.params;
    const { startDate, endDate } = req.query;
    const userId = req.user._id;

    console.log('查询设备数据:', {
      deviceId,
      userId,
      startDate,
      endDate
    });

    // 验证设备所有权
    const device = await Device.findOne({ deviceId, userId });
    if (!device) {
      console.log('设备不存在或无权访问:', { deviceId, userId });
      res.status(404).json({ message: '设备不存在或无权访问' });
      return;
    }

    // 构建查询条件
    const query: any = { 
      deviceId,
      userId
    };

    // 只有当 startDate 和 endDate 都有值时才添加时间范围条件
    if (startDate && endDate && startDate !== '' && endDate !== '') {
      const start = new Date(startDate as string);
      const end = new Date(endDate as string);
      
      if (!isNaN(start.getTime()) && !isNaN(end.getTime())) {
        query.timestamp = {
          $gte: start,
          $lte: end
        };
      }
    }

    console.log('查询条件:', query);

    // 执行查询
    const data = await DeviceData.find(query)
      .sort({ timestamp: -1 })
      .limit(1000);

    console.log('查询结果数量:', data.length);

    res.json(data);
  } catch (error) {
    console.error('获取设备数据失败:', error);
    res.status(500).json({ message: '获取设备数据失败', error });
  }
};

export const sendCommand = async (req: Request, res: Response): Promise<void> => {
  try {
    const { deviceId } = req.params;
    const { command, params } = req.body;
    const userId = req.user._id;

    // 验证设备所有权
    const device = await Device.findOne({ deviceId, userId });
    if (!device) {
      res.status(404).json({ message: '设备不存在或无权访问' });
      return;
    }

    if (device.status !== 'online') {
      res.status(400).json({ message: '设备离线，无法发送命令' });
      return;
    }

    mqttService.publish(`device/${deviceId}/command`, {
      command,
      params,
      timestamp: new Date()
    });

    res.json({ message: '命令已发送' });
  } catch (error) {
    res.status(500).json({ message: '发送命令失败', error });
  }
};

export const getDevice = async (req: Request, res: Response): Promise<void> => {
  try {
    const { deviceId } = req.params;
    const userId = req.user._id;

    const device = await Device.findOne({ deviceId, userId });
    if (!device) {
      res.status(404).json({ message: '设备不存在或无权访问' });
      return;
    }

    res.json(device);
  } catch (error) {
    res.status(500).json({ message: '获取设备信息失败', error });
  }
};

export const updateDevice = async (req: Request, res: Response): Promise<void> => {
  try {
    const { deviceId } = req.params;
    const { name, type } = req.body;
    const userId = req.user._id;

    const device = await Device.findOneAndUpdate(
      { deviceId, userId },
      { name, type },
      { new: true }
    );

    if (!device) {
      res.status(404).json({ message: '设备不存在或无权更新' });
      return;
    }

    // 广播设备更新
    const stats = await mqttService.getDeviceStats(userId.toString());
    broadcast('deviceUpdate', stats);

    res.json(device);
  } catch (error) {
    res.status(500).json({ message: '更新设备失败', error });
  }
};

export const updateFirmware = async (req: Request, res: Response): Promise<void> => {
  try {
    const { deviceId } = req.params;
    const firmwareFile = req.file;
    const userId = req.user._id;

    if (!firmwareFile) {
      res.status(400).json({ message: '未找到固件文件' });
      return;
    }

    // 验证设备所有权
    const device = await Device.findOne({ deviceId, userId });
    if (!device) {
      // 删除上传的文件
      fs.unlinkSync(firmwareFile.path);
      res.status(404).json({ message: '设备不存在或无权访问' });
      return;
    }

    if (device.status !== 'online') {
      // 删除上传的文件
      fs.unlinkSync(firmwareFile.path);
      res.status(400).json({ message: '设备离线，无法更新固件' });
      return;
    }

    // 读取固件文件内容
    const firmwareData = fs.readFileSync(firmwareFile.path);
    
    // 发送固件更新命令
    mqttService.publish(`device/${deviceId}/command`, {
      command: 'update_firmware',
      params: {
        firmware: firmwareData.toString('base64'),
        filename: firmwareFile.originalname
      },
      timestamp: new Date()
    });

    // 删除临时文件
    fs.unlinkSync(firmwareFile.path);

    res.json({ message: '固件更新命令已发送' });
  } catch (error: any) {
    // 如果上传了文件但处理失败，删除文件
    if (req.file) {
      fs.unlinkSync(req.file.path);
    }
    res.status(500).json({ message: error.message || '固件更新失败' });
  }
};

// 设备参数配置接口
export const getDeviceConfig = async (req: Request, res: Response): Promise<void> => {
  try {
    const { deviceId } = req.params;
    const userId = req.user._id;

    // 验证设备所有权
    const device = await Device.findOne({ deviceId, userId });
    if (!device) {
      res.status(404).json({ message: '设备不存在或无权访问' });
      return;
    }

    // 如果设备在线，尝试获取实时配置
    if (device.status === 'online') {
      mqttService.publish(`device/${deviceId}/command`, {
        command: 'get_config',
        params: {},
        timestamp: new Date()
      });
    }

    // 返回设备当前配置或默认配置
    const config = device.config || {
      samplingInterval: 60, // 采样间隔（秒）
      uploadInterval: 300,  // 上传间隔（秒）
      alarmThresholds: {
        temperature: {
          high: 30,
          low: 10
        },
        humidity: {
          high: 80,
          low: 20
        }
      },
      wifi: {
        ssid: '',
        password: ''
      },
      mqtt: {
        server: 'mqtt://localhost:1883',
        username: '',
        password: ''
      }
    };

    res.json(config);
  } catch (error) {
    res.status(500).json({ message: '获取设备配置失败', error });
  }
};

export const updateDeviceConfig = async (req: Request, res: Response): Promise<void> => {
  try {
    const { deviceId } = req.params;
    const config = req.body;
    const userId = req.user._id;

    // 验证设备所有权
    const device = await Device.findOne({ deviceId, userId });
    if (!device) {
      res.status(404).json({ message: '设备不存在或无权访问' });
      return;
    }

    // 保存配置到数据库
    device.config = config;
    await device.save();

    // 如果设备在线，发送配置更新命令
    if (device.status === 'online') {
      mqttService.publish(`device/${deviceId}/command`, {
        command: 'update_config',
        params: config,
        timestamp: new Date()
      });
    }

    res.json({ 
      message: device.status === 'online' ? '配置已更新并发送到设备' : '配置已保存，将在设备上线时更新',
      config 
    });
  } catch (error) {
    res.status(500).json({ message: '更新设备配置失败', error });
  }
};

// 文件转二进制发送接口
export const sendBinaryFile = async (req: Request, res: Response): Promise<void> => {
  try {
    const { deviceId } = req.params;
    const { fileType } = req.body;
    const file = req.file;
    const userId = req.user._id;

    if (!file) {
      res.status(400).json({ message: '未找到文件' });
      return;
    }

    // 验证设备所有权
    const device = await Device.findOne({ deviceId, userId });
    if (!device) {
      fs.unlinkSync(file.path);
      res.status(404).json({ message: '设备不存在或无权访问' });
      return;
    }

    if (device.status !== 'online') {
      fs.unlinkSync(file.path);
      res.status(400).json({ message: '设备离线，无法发送文件' });
      return;
    }

    // 读取文件内容
    const fileData = fs.readFileSync(file.path);
    
    // 发送文件数据
    mqttService.publish(`device/${deviceId}/command`, {
      command: 'receive_file',
      params: {
        type: fileType,
        data: fileData.toString('base64'),
        filename: file.originalname
      },
      timestamp: new Date()
    });

    // 删除临时文件
    fs.unlinkSync(file.path);

    res.json({ message: '文件发送命令已发送' });
  } catch (error: any) {
    if (req.file) {
      fs.unlinkSync(req.file.path);
    }
    res.status(500).json({ message: error.message || '发送文件失败' });
  }
};

export const saveDeviceData = async (req: Request, res: Response): Promise<void> => {
  try {
    const { deviceId } = req.params;
    const { temperature, humidity, battery, signal } = req.body;
    const userId = req.user._id;

    console.log('保存设备数据:', {
      deviceId,
      userId,
      temperature,
      humidity,
      battery,
      signal
    });

    // 验证设备所有权
    const device = await Device.findOne({ deviceId, userId });
    if (!device) {
      console.log('设备不存在或无权访问:', { deviceId, userId });
      res.status(404).json({ message: '设备不存在或无权访问' });
      return;
    }

    // 创建设备数据记录
    const deviceData = new DeviceData({
      deviceId,
      userId,
      timestamp: new Date(),
      data: {
        temperature: temperature !== undefined ? Number(temperature) : undefined,
        humidity: humidity !== undefined ? Number(humidity) : undefined,
        battery: battery !== undefined ? Number(battery) : undefined,
        signal: signal !== undefined ? Number(signal) : undefined
      },
      metadata: {
        firmwareVersion: device.config?.firmwareVersion,
        ipAddress: device.config?.wifi?.ssid ? 'Connected' : undefined,
        connectionType: device.config?.wifi?.ssid ? 'wifi' : 'ethernet',
        signalStrength: device.config?.wifi?.signalStrength
      }
    });

    console.log('准备保存的设备数据:', deviceData);

    // 保存数据
    const savedData = await deviceData.save();
    console.log('设备数据保存成功:', savedData);

    // 更新设备状态
    if (temperature !== undefined) device.temperature = Number(temperature);
    if (humidity !== undefined) device.humidity = Number(humidity);
    device.lastHeartbeat = new Date();
    await device.save();

    console.log('设备状态更新成功');

    res.status(201).json(savedData);
  } catch (error) {
    console.error('保存设备数据失败:', error);
    res.status(500).json({ message: '保存设备数据失败', error });
  }
}; 